package live.jialing.sip.base.service;

import com.google.common.collect.Lists;
import live.jialing.authz.domain.SecurityGroup;
import live.jialing.authz.service.SecurityGroupService;
import live.jialing.core.data.LinkType;
import live.jialing.core.data.jpa.CustomJpaRepository;
import live.jialing.core.exception.ServiceException;
import live.jialing.core.service.BaseDomainService;
import live.jialing.core.service.GeneralService;
import live.jialing.data.util.SpecificationUtil;
import live.jialing.sip.base.dict.ClassCategoryEnum;
import live.jialing.sip.base.dict.SchoolCategoryEnum;
import live.jialing.sip.base.dict.SchoolRoleEnum;
import live.jialing.sip.base.dict.SchoolTitleEnum;
import live.jialing.sip.base.domain.School;
import live.jialing.sip.base.repository.SchoolRepository;
import live.jialing.sip.base.util.SchoolUtil;
import live.jialing.sip.base.vo.GradeVO;
import live.jialing.structure.domain.Employee;
import live.jialing.structure.domain.Position;
import live.jialing.structure.repository.PositionRepository;
import live.jialing.structure.service.EmployeeService;
import live.jialing.util.general.Collections3;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 学校
 */
@Service
public class SchoolService extends BaseDomainService<School, Long> implements GeneralService<School, Long> {

    private static Logger logger = LoggerFactory.getLogger(SchoolService.class);

    @Resource
    private SchoolRepository schoolRepository;

    @Resource
    private EmployeeService employeeService;

    @Resource
    private SecurityGroupService securityGroupService;

    @Resource
    private PositionRepository positionRepository;

    @Override
    public CustomJpaRepository getRepository() {
        return this.schoolRepository;
    }

    public Specification<School> buildSpecification(java.lang.Class<School> classz, Map<String, Object> searchParams, LinkType type) {

        return SpecificationUtil.buildSpecification(classz, searchParams, type);
    }

    /**
     * 设置学校校长<br>
     * 已经是本校员工的，设置为校长
     *
     * @param schoolId   学校ID
     * @param employeeId 员工ID
     */
    @Transactional
    public void setupSchoolMaster(long schoolId, long employeeId) {

        if (schoolId < 1 || employeeId < 1) {
            logger.warn("参数错误：schoolId={}，employeeId={}", schoolId, employeeId);
            return;
        }

        Employee employee = employeeService.findEmployeeInOrg(schoolId, employeeId);
        if (employee == null) {
            throw new ServiceException("本校无此员工");
        }

        // 职务设置新的校长
        // 设置
        Position post = new Position();
        post.setTitle(SchoolTitleEnum.SCH_MASTER.toString());
        post.setEmployeeId(employee.getId());
        post.setCompanyId(schoolId);
        positionRepository.save(post);

        // 设置为校长角色
        SecurityGroup securityGroup = securityGroupService.findSecurityGroupInOrgByCode(schoolId, SchoolRoleEnum.SCH_MASTER.toString());
        securityGroupService.setupUsers(securityGroup.getId(), schoolId, Lists.newArrayList(employeeId));
    }

    /**
     * 删除校长
     *
     * @param schoolId   学校ID
     * @param employeeId 员工ID
     */
    @Transactional
    public void unSetupSchoolMaster(long schoolId, long employeeId) {

        if (schoolId < 1 || employeeId < 1) {
            logger.warn("参数错误：schoolId={}，employeeId={},newEmployeeId={}", schoolId, employeeId);
            return;
        }

        // 删除之前的校长职务
        List<Position> masters = positionRepository.findByCompanyAndEmployeeAndTitle(schoolId, employeeId, SchoolTitleEnum.SCH_MASTER.toString());
        positionRepository.delete(masters);

        //
        // 删除该员工的校长角色
        SecurityGroup securityGroup = securityGroupService.findSecurityGroupInOrgByCode(schoolId, SchoolRoleEnum.SCH_MASTER.toString());
        securityGroupService.removeUsers(securityGroup.getId(), schoolId, Lists.newArrayList(employeeId));

    }

    /**
     * 设置学校领导（多个）
     *
     * @param schoolId    学校ID
     * @param employeeIds 员工ID集合
     */
    @Transactional
    public void setupSchoolLeader(long schoolId, List<Long> employeeIds) {

        if (schoolId < 1 || Collections3.isEmpty(employeeIds)) {
            logger.warn("参数错误：schoolId={}", schoolId);
            return;
        }

        List<Employee> employees = employeeService.findEmployeeInOrg(schoolId, employeeIds);
        if (employeeIds.size() != employeeIds.size()) {
            throw new ServiceException("输入的员工与学校的员工对不上");
        }

        // 设置职务
        List<Position> list = employees.stream().map(employee -> {
            Position post = new Position();
            post.setTitle(SchoolTitleEnum.SCH_LEADER.toString());
            post.setEmployeeId(employee.getId());
            post.setCompanyId(schoolId);
            return post;
        }).collect(Collectors.toList());
        positionRepository.save(list);

        // 设置为校领导角色
        SecurityGroup securityGroup = securityGroupService.findSecurityGroupInOrgByCode(schoolId, SchoolRoleEnum.SCH_LEADER.toString());
        securityGroupService.setupUsers(securityGroup.getId(), schoolId, employeeIds);
    }

    /**
     * 删除学校领导
     *
     * @param schoolId   学校ID
     * @param employeeId 老校领导的员工ID
     */
    @Transactional
    public void updateSchoolLeader(long schoolId, long employeeId) {

        if (schoolId < 1 || employeeId < 1) {
            logger.warn("参数错误：schoolId={},employeeId={}", schoolId, employeeId);
            return;
        }

        // 删除之前的校领导职务
        List<Position> masters = positionRepository.findByCompanyAndEmployeeAndTitle(schoolId, employeeId, SchoolTitleEnum.SCH_LEADER.toString());
        positionRepository.delete(masters);

        //
        // 删除该员工的校领导角色
        SecurityGroup securityGroup = securityGroupService.findSecurityGroupInOrgByCode(schoolId, SchoolRoleEnum.SCH_LEADER.toString());
        securityGroupService.removeUsers(securityGroup.getId(), schoolId, Lists.newArrayList(employeeId));
    }

    /**
     * 学校添加新教职工
     *
     * @param schoolId
     * @param employees
     */
    @Transactional
    public void addEmployees(Long schoolId, List<Employee> employees) {

        if (schoolId == null || schoolId.longValue() < 1) {
            throw new ServiceException("学校ID不能为空");
        }

        School school = this.findByPK(schoolId);
        if (school == null) {
            throw new ServiceException("学校ID不正确，没有此ID的学校");
        }

        employees.stream().forEach(t -> {
            t.setCompany(school);
        });

        employeeService.batchAdd(employees);
    }

    /**
     * 获取所有在读的年级
     *
     * @param schoolId 学校id
     * @return
     */
    public List<GradeVO> findOnlineGrade(long schoolId) {

        if (schoolId < 1) {
            return Lists.newArrayList();
        }

        School school = this.findByPK(schoolId);

        SchoolCategoryEnum category = school.getCategory();
        LocalDate localDate = LocalDate.now();
        // 最大年级，如果当前月份小于9月则为去年，否则为今年
        int maxGrade = localDate.getMonthValue() < 9 ? localDate.getYear() - 1 : localDate.getYear();
        List<GradeVO> grades = Lists.newArrayList();
        if (category == SchoolCategoryEnum.H || category == SchoolCategoryEnum.HM || category == SchoolCategoryEnum.HMS) {
            for (int i = 0; i < 3; i++) {
                GradeVO vo = new GradeVO();
                vo.setCategory(ClassCategoryEnum.H);
                vo.setInYear(maxGrade - i);
                vo.setName(SchoolUtil.gradeName(vo.getCategory(), vo.getInYear()));
                grades.add(vo);
            }
        }

        if (category == SchoolCategoryEnum.M || category == SchoolCategoryEnum.HM || category == SchoolCategoryEnum.HMS) {
            for (int i = 0; i < 3; i++) {
                GradeVO vo = new GradeVO();
                vo.setCategory(ClassCategoryEnum.M);
                vo.setInYear(maxGrade - i);
                vo.setName(SchoolUtil.gradeName(vo.getCategory(), vo.getInYear()));
                grades.add(vo);
            }
        }

        if (category == SchoolCategoryEnum.S || category == SchoolCategoryEnum.HMS) {
            for (int i = 0; i < 6; i++) {
                GradeVO vo = new GradeVO();
                vo.setCategory(ClassCategoryEnum.S);
                vo.setInYear(maxGrade - i);
                vo.setName(SchoolUtil.gradeName(vo.getCategory(), vo.getInYear()));
                grades.add(vo);
            }
        }

        return grades;
    }
}
